Overview

In the previous assignment, we took the RNASeq data from the publication Cannabidiol inhibits SARS-COV-2 replication and promotes the host innate immune response by Nguyen et al., cleaned the data, performed normalization, gene identifier mapping, and some additional preliminary analysis on the dataset. As suggested by the title, the authors of the publication studied the effects of cannabidiol on SARS-CoV-2 replication and host’s immune response. The authors hypothesized and concluded that cannabidiol inhibits SARS-CoV-2 replication by up-regulating the host IRE1α ribonuclease endoplasmic reticulum (ER) stress response and interferon signaling pathways. The experiment conditions from in the dataset can be categorized into

with 3 replicates for each test condition.

We obtained the dataset from GEO with ID GSE168797, associated with the study Cannabidiol inhibits SARS-COV-2 replication and promotes the host innate immune response published on Science Advances. Out of the total of 57832 genes, 13705 remained after removing low counts and genes with duplicate identifiers.

Data normalization is performed using TMM with the edgeR package. Normalization corrects the large deviation of the means of untreated groups from the groups treated with CBD, while still preserving some of the characteristics of the original sample distribution.

We observe separation of groups after normalization.

We will revisit this figure later when performing differential gene expression analysis.

Identifier mapping was performed using the package biomaRt with data from Ensembl. The Ensembl gene IDs in the original dataset are mapped to the corresponding HUGO gene symbols. The final dataset included 13705 genes with unique identifiers.

Setup

In this section, we import and install the necessary packages for this assignment, in which we will conduct a differential expression analysis using the normalized dataset and a thresholded over-representation analysis.

Differential Expression Analysis using edgeR

In this section, we are going to perform differential expression analysis.

Let us first examine the normalized data.

Normalized gene counts
CBD_infect-1 CBD_infect-2 CBD_infect-3 Veh_infect-1 Veh_infect-2 Veh_infect-3
TSPAN6 31.887883 34.611576 36.856052 27.579725 26.797481 25.940554
DPM1 50.041084 51.301886 54.306630 45.221632 44.700001 45.116977
SCYL3 10.913215 9.376985 9.433715 18.667599 17.497179 19.244748
C1orf112 7.790084 9.467497 9.917955 17.755873 17.587255 19.335847
CFH 17.425654 19.731495 18.365254 29.699489 23.194459 29.037933
FUCA2 47.893932 54.397378 54.772936 33.460361 31.796675 31.588716
GCLC 149.679627 160.893142 162.830217 107.652101 100.186550 108.271635
NFYA 20.903687 23.514873 24.893528 36.446265 40.443930 38.421171
STPG1 16.094774 12.888830 13.253831 6.496051 6.575516 7.082978
NIPAL3 23.512212 21.306394 20.822324 12.559032 11.642267 9.770410
Sample groups
group lib.size norm.factors
CBD_infect-1 CBD 673771.1 1
CBD_infect-2 CBD 677449.4 1
CBD_infect-3 CBD 685317.7 1
Veh_infect-1 Veh 782981.3 1
Veh_infect-2 Veh 781343.9 1
Veh_infect-3 Veh 793046.5 1

Workflow

We will be calculating differential expression following this general workflow:

  1. Create deisng matrix. We will ensure that all factors that could contribute to differential expression is accounted for in the design matrix.

  2. Use a mean-variance plot to confirm that the data follows the negative binomial distribution assumption for using the quasi-likelihood model in edgeR.

  3. Fit our data to the model and calculated p-value and corrected p-value.

  4. Use a threshold to extract differentially expressed genes with statistically significant differences.

  5. Plot and visualize.

Creating the Design Matrix

In order to perform statistical testing, we need a design matrix the defines our model. Notice that in our dataset, there are three factors:

  1. Treatment with CBD
  2. Infection status (infected or not)
  3. Patient

Hence, ideally, we would like to account for all three factors in our design matrix.

Design matrix
(Intercept) samples$patient2 samples$patient3 samples$cbd_treatmentCBD samples$infectedmock
1 0 0 1 0
1 1 0 1 0
1 0 1 1 0
1 0 0 0 0
1 1 0 0 0
1 0 1 0 0
1 0 0 1 1
1 1 0 1 1
1 0 1 1 1
1 0 0 0 1
1 1 0 0 1
1 0 1 0 1

Distribution of Data

For our downstream analysis, we are going to use edgeR. We chose edgeR because it is specifically designed for RNASeq data. However, one important underlying assumption for using the quasi-likelihood model is that the data follows a negative binomial distribution. We need to verify that our dataset indeed meets that assumption.

Let us the calculate the dispersion and plot to visualize the mean-variance relationship.

edgeR::plotMeanVar(d,
                   show.raw.vars = TRUE,
                   show.tagwise.vars = TRUE,
                   NBline = TRUE,
                   show.ave.raw.vars = TRUE,
                   show.binned.common.disp.vars = TRUE,
                   main = "Mean-Variance Plot for Variance and Dispersion of Our Data")
# display legend
legend("topleft", 
       legend=c("Raw Data", "Tagwise Dispersion", "Average Raw Variances", 
                "Binned Common Dispersion", "Negative Binomial Line"), 
       col = c("grey", "lightblue", "maroon", "red", "dodgerblue2"), pch=c(1,1,4,4,NA), lty=c(0,0,0,0,1), lwd=c(1,1,1,1,2), cex=0.6)

As demonstrated by the mean-variance plot above, we can see that the dispersion and variance of our data indeed roughly follows the negative binomial distribution.

Analysis Using edgeR

Now, we have created the design matrix and verified the assumption for the data to be negative-binomially distributed, we can proceed to the next stage of our analysis and perform statistical testing and corrections to ensure that we only get significantly differentially expressed genes. We used the quasi-likelihood models since our dataset is from an RNASeq experiment and quasi-likelihood models are best suited to handle RNASeq data.

Once we have fit the model, we can proceed to calculate differential expression. Recall that our goal is to verify the role of cannabidiol in affecting the replication ability of SARS-CoV-2, so we will be using cbd_treatment as the contrast.

Top differentially expressed genes
logFC logCPM F PValue FDR
DNAJB9 3.296477 6.632298 2376.139 1.174076e-13 1.225637e-09
IGFBP1 4.315555 7.225448 2191.283 1.788598e-13 1.225637e-09
HSPA5 3.721184 11.833327 1920.096 3.552926e-13 1.623095e-09
CRELD2 3.023632 6.669438 1395.860 1.858463e-12 5.742205e-09
KIF20A -2.327554 5.891384 1344.930 2.253309e-12 5.742205e-09
ADGRF4 2.315894 4.618755 1287.278 2.827571e-12 5.742205e-09
GABARAPL1 2.351451 6.414219 1278.222 2.932903e-12 5.742205e-09
NDRG4 1.776359 6.129025 1133.516 5.463712e-12 9.159587e-09
HERPUD1 3.400467 8.195296 1061.159 7.686235e-12 9.159587e-09
STC2 2.742212 6.444858 1059.247 7.758262e-12 9.159587e-09

We can examine the number of genes pass the threshold and correction. We are using 0.05 as the threshold for p-value as it is commonly used in practice.

The threshold of 0.05 gives us quite a lot of genes, in order to get more meaningful hits in the downstream gene enrichment analysis, we will make the thershold more stringent.

Visualization of Differentially Expressed Genes

Now we can retrieve the list of differential expressed genes and visualize using different plots. We will first plot them on a volcano plot. Each gene is represented by a point in the plot. The horizontal axis of the plot is the \(\log_2\) fold change and the vertical axis is the \(-\log_{10}p\) which indicates the statistical significance of each gene (how likely the differential is due to actual biological variation).

Next, we will visualize the upregulated and downregulated genes across different test conditions using a heatmap.

Discussion

  1. Initially, I used the p-value of 0.05 as it is widely used in practice. This gives us 5501 genes prior to correction. This is quite a large number of genes, so we changed the p-value threshold to 0.01 to limit the number of genes included. We further added the criteria that a gene must have an absolute log fold change greater than 1.5. By doing so, we are contraining ourselves to only get the genes that are highly differentially expressed with high statistical significance.

  2. For correction, we used Benjamini-Hochberg. The two main methods discussed for correcting family-wise false discovery rate are Bonferroni and Benjamini-Hochberg correction. We want to get meaningful hits without excluding statistically significant ones. Bonferroni’s method is overly stringent so it is not quite suitable for our purposes. Using Benjamini-Hochberg will give us a richer set of genes that we can use for downstream analysis.

  3. Volcano plot shown above. Note that we also applied the restriction that only genes with aboslute log fold change greater than 1.5 are to be included.

  4. There is significant clustering within conditions. This suggests that the test condition (CBD v.s. no CBD) does have a significant effect on gene expressions.

Thresholded Overrepresentation Analysis using g:Profiler

For the final part of this assignment, we will perform a thresholded overrepresentation analysis using g:Profiler. In the previous section, we have compiled a list of differentially expressed genes. Here, we want to further divide them into upregulated and downregulated genes.

upregulated_gene_lst <- diff_exp_lst[diff_exp_lst$logFC > 0,]
downregulated_gene_lst <- diff_exp_lst[diff_exp_lst$logFC < 0,]

We use the R package for g:Profiler to perform the gene enrichment analysis. For correction, we used FDR as it is less stringent than Bonferroni and is introduced as the preferred correction method in class. We used GO Biological Process, GO Molecular Function, and KEGG as those are the ones used by the author of the original publication. For a more detailed overview of the workflow, please refer to the Discussion subsection located at the end of this section.

Upregulated Genes

Top genesets using list of upregulated genes
term_name term_id source
response to endoplasmic reticulum stress GO:0034976 GO:BP
proteasomal protein catabolic process GO:0010498 GO:BP
ERAD pathway GO:0036503 GO:BP
ubiquitin-dependent ERAD pathway GO:0030433 GO:BP
proteasome-mediated ubiquitin-dependent protein catabolic process GO:0043161 GO:BP
autophagy GO:0006914 GO:BP
process utilizing autophagic mechanism GO:0061919 GO:BP
response to topologically incorrect protein GO:0035966 GO:BP
macroautophagy GO:0016236 GO:BP
endoplasmic reticulum to Golgi vesicle-mediated transport GO:0006888 GO:BP

For context, let’s examine the top term from each data source.

Top terms from each data source using list of upregulated genes
term_name term_id source
1 response to endoplasmic reticulum stress GO:0034976 GO:BP
331 unfolded protein binding GO:0051082 GO:MF
401 Protein processing in endoplasmic reticulum KEGG:04141 KEGG

We can visualize the distribution of top terms from each data source using an Manhattan plot. This is the distribution of terms prior to removing large terms with over 500 genes.

gprofiler2::gostplot(up_top_terms_all) %>% plotly::layout(title = "Manhattan plot showing distribution of terms \nfrom each data source using list of upregulated genes", font = list(size = 10))

Downregulated Genes

We do the same for the downregualted genes.

Top genesets using list of downregulated genes
term_name term_id source
mitotic nuclear division GO:0140014 GO:BP
sister chromatid segregation GO:0000819 GO:BP
mitotic sister chromatid segregation GO:0000070 GO:BP
nuclear division GO:0000280 GO:BP
chromosome segregation GO:0007059 GO:BP
organelle fission GO:0048285 GO:BP
nuclear chromosome segregation GO:0098813 GO:BP
cell cycle phase transition GO:0044770 GO:BP
regulation of cell cycle phase transition GO:1901987 GO:BP
DNA replication GO:0006260 GO:BP
Top terms from each data source using list of downregulated genes
term_name term_id source
1 mitotic nuclear division GO:0140014 GO:BP
474 chromatin binding GO:0003682 GO:MF
535 Cell cycle KEGG:04110 KEGG

Plot the Manhattan plot showing distribution of terms from each data source using list of downregulated genes.

gprofiler2::gostplot(down_top_terms_all) %>% plotly::layout(title = "Manhattan plot showing distribution of terms\n from each data source using list of downregulated genes", font = list(size = 10))

All Differentially Expressed Genes

Finally, for all differentially expressed genes.

Top genesets using list of all differentially expressed genes
term_name term_id source
mitotic sister chromatid segregation GO:0000070 GO:BP
mitotic nuclear division GO:0140014 GO:BP
sister chromatid segregation GO:0000819 GO:BP
response to endoplasmic reticulum stress GO:0034976 GO:BP
proteasomal protein catabolic process GO:0010498 GO:BP
organelle fission GO:0048285 GO:BP
chromosome segregation GO:0007059 GO:BP
nuclear chromosome segregation GO:0098813 GO:BP
nuclear division GO:0000280 GO:BP
regulation of cell cycle phase transition GO:1901987 GO:BP
Top terms from each data source using list of all differentially expressed genes
term_name term_id source
1 mitotic sister chromatid segregation GO:0000070 GO:BP
514 cadherin binding GO:0045296 GO:MF
583 Protein processing in endoplasmic reticulum KEGG:04141 KEGG
gprofiler2::gostplot(top_terms_all) %>% plotly::layout(title = "Manhattan plot showing distribution of terms from each data source", font = list(size = 10))

Discussion

  1. We used g:Profiler as we have extensively discussed about it in class. It has a nice web-based interface as well as easy-to-use APIs in the form of an R package. Furthermore, the data sources on g:Profiler is frequently updated and include the data sources that we are most interested in.

  2. We used GO Biological Process, GO Molecular Function, and KEGO. We chose these data sources since they are also used by the author of the original paper from which I obtained the dataset. However, since KEGO is a commercial data source, if it was not for that fact that the original paper used it, I would personally refrain from using it. The original author also used other data sources including Canonical Pathways but since it is not part of g:Profiler, we did not include these data sources. The annotation source versions are as follows: Ensembl 105, Ensembl Genomes 52 (database built on 2022-02-14)

  3. For all three analysis (using upregulated, downregulated, all differentially expressed), we used a threshold between 2 and 500. We set the upper bound to 500 because we do not want to include overly broad and generic terms that will not give us meaningful insights into the roles of the differentially expressed genes. The set of upregulated genes returned 433 genesets; the set of downregulated genes returned 560 genesets; the set of all differentially expressed genes returned 616 gene sets.

  4. The result using the whole list (set of all differentially expressed genes) is more predominantly represented by the downregulated genes. It also does not provide a lot of insights into the roles of the genes as it is a mix of drastically different and seemingly unrelated terms (e.g. mitotic nuclear division, organelle fission, response to endoplasmic reticulum stress, etc.). However, by using separating into upregualted and downregulated genes and performing the gene enrichment analysis separately, we get more meaningful terms: the upregualted genes are mostly associated with pathways and processes involving endoplasmic reticulum whereas the downregulated genes are mostly associated with the cell cycle.

Interpretation

  1. Yes. The overrepresentation analysis results support the conclusion discussed in the original paper. The original paper claims that CBD treatment can inhibit SARS-CoV-2 replication through the host’s ER stress response pathway. Although we were not able to verify whether or not this has any affect on SARS-CoV-2 replication, we are able to confirm based on the top terms returned by the overrepresentation analysis that the genes associated with ER stress response are indeed upregulated in the samples treated with CBD.

  2. The conclusion that CBD is correlated to reduced risk or severity of SARS-CoV-2 is supported by testing adult patients as presented by the original paper. There are also other papers who discussed the role of CBD in SARS-CoV-2 infection (van Breeman et al.). The result from our overrepresentation analysis is supported by the original paper, in which the author has also performed gene enrichment analysis with similar outcomes. However, since this is still an early research in this topic and SARS-CoV-2 continues to evolve, there does not seem to be other unrelated groups who could provide additional supporting evidence to our results from the overrepresentation analysis besides the original paper.

Journal

Link to my journal entry for this assignment: https://github.com/bcb420-2022/Kevin_Gao/wiki/Assignment-2

References

LS0tCnRpdGxlOiAiS2V2aW4gR2FvIC0gQXNzaWdubWVudCAyOiBEaWZmZXJlbnRpYWwgR2VuZSBleHByZXNzaW9uIGFuZCBQcmVsaW1pbmFyeSBPUkEiCm91dHB1dDogCiAgaHRtbF9ub3RlYm9vazoKICAgIHRvYzogdHJ1ZQogICAgdG9jX2RlcHRoOiAyCiAgICBtYXRoamF4OiAiaHR0cHM6Ly9jZG5qcy5jbG91ZGZsYXJlLmNvbS9hamF4L2xpYnMvbWF0aGpheC8yLjcuNy9NYXRoSmF4LmpzP2NvbmZpZz1UZVgtTU1MLUFNX0NIVE1MIgotLS0KCiMgT3ZlcnZpZXcKCmBgYHtyIGExX3NvdXJjZSwgaW5jbHVkZT1GQUxTRSwgcmVzdWx0cz0naGlkZScsZWNobz1GQUxTRSwgbWVzc2FnZT1GQUxTRSwgcmVzdWx0cz0naGlkZSd9Cm9wdGlvbnMod2Fybj0tMSkKYTFfb3V0cHV0IDwtIGtuaXRyOjprbml0X2NoaWxkKCdhc3NpZ25tZW50MS5SbWQnLCBxdWlldCA9IFRSVUUpCmBgYAoKSW4gdGhlIHByZXZpb3VzIGFzc2lnbm1lbnQsIHdlIHRvb2sgdGhlIFJOQVNlcSBkYXRhIGZyb20gdGhlIHB1YmxpY2F0aW9uICpDYW5uYWJpZGlvbCBpbmhpYml0cyBTQVJTLUNPVi0yIHJlcGxpY2F0aW9uIGFuZCBwcm9tb3RlcyB0aGUgaG9zdCBpbm5hdGUgaW1tdW5lIHJlc3BvbnNlKiBieSBOZ3V5ZW4gZXQgYWwuLCBjbGVhbmVkIHRoZSBkYXRhLCBwZXJmb3JtZWQgbm9ybWFsaXphdGlvbiwgZ2VuZSBpZGVudGlmaWVyIG1hcHBpbmcsIGFuZCBzb21lIGFkZGl0aW9uYWwgcHJlbGltaW5hcnkgYW5hbHlzaXMgb24gdGhlIGRhdGFzZXQuIEFzIHN1Z2dlc3RlZCBieSB0aGUgdGl0bGUsIHRoZSBhdXRob3JzIG9mIHRoZSBwdWJsaWNhdGlvbiBzdHVkaWVkIHRoZSBlZmZlY3RzIG9mIGNhbm5hYmlkaW9sIG9uIFNBUlMtQ29WLTIgcmVwbGljYXRpb24gYW5kIGhvc3QncyBpbW11bmUgcmVzcG9uc2UuIFRoZSBhdXRob3JzIGh5cG90aGVzaXplZCBhbmQgY29uY2x1ZGVkIHRoYXQgY2FubmFiaWRpb2wgaW5oaWJpdHMgU0FSUy1Db1YtMiByZXBsaWNhdGlvbiBieSB1cC1yZWd1bGF0aW5nIHRoZSBob3N0IElSRTHOsSByaWJvbnVjbGVhc2UgZW5kb3BsYXNtaWMgcmV0aWN1bHVtIChFUikgc3RyZXNzIHJlc3BvbnNlIGFuZCBpbnRlcmZlcm9uIHNpZ25hbGluZyBwYXRod2F5cy4gVGhlIGV4cGVyaW1lbnQgY29uZGl0aW9ucyBmcm9tIGluIHRoZSBkYXRhc2V0IGNhbiBiZSBjYXRlZ29yaXplZCBpbnRvCgotIEluZmVjdGlvbiB3aXRoIFNBUlMtQ29WLTIsIG5vIHRyZWF0bWVudAotIEluZmVjdGlvbiB3aXRoIFNBUlMtQ29WLTIsIHRyZWF0bWVudCB3aXRoIENhbm5hYmlkaW9sCi0gTm8gaW5mZWN0aW9uLCBubyB0cmVhdG1lbnQKLSBObyBpbmZlY3Rpb24sIHRyZWF0bWVudCB3aXRoIENhbm5hYmlkaW9sCgp3aXRoIDMgcmVwbGljYXRlcyBmb3IgZWFjaCB0ZXN0IGNvbmRpdGlvbi4KCldlIG9idGFpbmVkIHRoZSBkYXRhc2V0IGZyb20gR0VPIHdpdGggSUQgR1NFMTY4Nzk3LCBhc3NvY2lhdGVkIHdpdGggdGhlIHN0dWR5ICpDYW5uYWJpZGlvbCBpbmhpYml0cyBTQVJTLUNPVi0yIHJlcGxpY2F0aW9uIGFuZCBwcm9tb3RlcyB0aGUgaG9zdCBpbm5hdGUgaW1tdW5lIHJlc3BvbnNlKiBwdWJsaXNoZWQgb24gU2NpZW5jZSBBZHZhbmNlcy4gT3V0IG9mIHRoZSB0b3RhbCBvZiA1NzgzMiBnZW5lcywgMTM3MDUgcmVtYWluZWQgYWZ0ZXIgcmVtb3ZpbmcgbG93IGNvdW50cyBhbmQgZ2VuZXMgd2l0aCBkdXBsaWNhdGUgaWRlbnRpZmllcnMuCgpEYXRhIG5vcm1hbGl6YXRpb24gaXMgcGVyZm9ybWVkIHVzaW5nIFRNTSB3aXRoIHRoZSBlZGdlUiBwYWNrYWdlLiBOb3JtYWxpemF0aW9uIGNvcnJlY3RzIHRoZSBsYXJnZSBkZXZpYXRpb24gb2YgdGhlIG1lYW5zIG9mIHVudHJlYXRlZCBncm91cHMgZnJvbSB0aGUgZ3JvdXBzIHRyZWF0ZWQgd2l0aCBDQkQsIHdoaWxlIHN0aWxsIHByZXNlcnZpbmcgc29tZSBvZiB0aGUgY2hhcmFjdGVyaXN0aWNzIG9mIHRoZSBvcmlnaW5hbCBzYW1wbGUgZGlzdHJpYnV0aW9uLgoKYGBge3Igbm9ybWFsaXplZF9kYXRhX3Bsb3QsIGVjaG89RkFMU0UsIG1lc3NhZ2U9RkFMU0UsIHJlc3VsdHM9J2hpZGUnfQpjb3VudHNfZGVuc2l0eV9ub3JtYWxpemVkIDwtIGFwcGx5KGxvZzIobm9ybWFsaXplZF9jb3VudHMpLCAyLCBkZW5zaXR5KQoKeGxpbSA8LSAwOyB5bGltIDwtIDAKZm9yIChpIGluIDE6bGVuZ3RoKGNvdW50c19kZW5zaXR5X25vcm1hbGl6ZWQpKSB7CiAgeGxpbSA8LSByYW5nZShjKHhsaW0sIGNvdW50c19kZW5zaXR5X25vcm1hbGl6ZWRbW2ldXSR4KSk7CiAgeWxpbSA8LSByYW5nZShjKHlsaW0sIGNvdW50c19kZW5zaXR5X25vcm1hbGl6ZWRbW2ldXSR5KSkKfQpjb2xzIDwtIHJhaW5ib3cobGVuZ3RoKGNvdW50c19kZW5zaXR5X25vcm1hbGl6ZWQpKQpsdHlzIDwtIHJlcCgxLCBsZW5ndGgoY291bnRzX2RlbnNpdHlfbm9ybWFsaXplZCkpCgpwbG90KGNvdW50c19kZW5zaXR5X25vcm1hbGl6ZWRbWzFdXSwgeGxpbSA9IHhsaW0sIHlsaW0gPSB5bGltLCB0eXBlID0gIm4iLCB5bGFiID0gIlNtb290aGluZyBkZW5zaXR5IG9mIGxvZzItQ1BNIiwgbWFpbiA9ICJEaXN0cmlidXRpb24gb2YgY291bnQgZGVuc2l0eSBmb3IgZWFjaCBleHBlcmltZW50IGNvbmRpdGlvbiAobm9ybWFsaXplZCkiLCBjZXgubGFiID0gMC44NSkKZm9yIChpIGluIDE6bGVuZ3RoKGNvdW50c19kZW5zaXR5X25vcm1hbGl6ZWQpKQogIGxpbmVzKGNvdW50c19kZW5zaXR5X25vcm1hbGl6ZWRbW2ldXSwgY29sID0gY29sc1tpXSwgbHR5ID0gbHR5c1tpXSkKbGVnZW5kKCJ0b3ByaWdodCIsIGNvbG5hbWVzKGRhdGEycGxvdCksIGNvbD1jb2xzLCBsdHk9bHR5cywgY2V4PTAuNzUsIGJvcmRlcj0iYmx1ZSIsIHRleHQuY29sID0gImdyZWVuNCIsIG1lcmdlID0gVFJVRSwgYmcgPSAiZ3JheTkwIikKYGBgCgpXZSBvYnNlcnZlIHNlcGFyYXRpb24gb2YgZ3JvdXBzIGFmdGVyIG5vcm1hbGl6YXRpb24uCgpgYGB7ciBhMV9tZHMsIGVjaG89RkFMU0UsIG1lc3NhZ2U9RkFMU0UsIHJlc3VsdHM9J2hpZGUnfQpsaW1tYTo6cGxvdE1EUyhsb2cyKG5vcm1hbGl6ZWRfY291bnRzKSwgbGFiZWxzPXJvd25hbWVzKHNhbXBsZXMpLCBjb2wgPSBjKCJkYXJrZ3JlZW4iLCJibHVlIilbZmFjdG9yKHNhbXBsZXMkY2JkX3RyZWF0bWVudCldLCBtYWluID0gIk1EUyBwbG90IGFmdGVyIG5vcm1hbGl6YXRpb24gc2hvd2luZyBkaXN0YW5jZXMgYmV0d2VlbiBzYW1wbGVzIikKbGVnZW5kKCJ0b3BsZWZ0IiwgbGVnZW5kPXJvd25hbWVzKHNhbXBsZXMpLCBmaWxsPWMoImRhcmtncmVlbiIsImJsdWUiKVtmYWN0b3Ioc2FtcGxlcyRjYmRfdHJlYXRtZW50KV0pCmBgYAoKV2Ugd2lsbCByZXZpc2l0IHRoaXMgZmlndXJlIGxhdGVyIHdoZW4gcGVyZm9ybWluZyBkaWZmZXJlbnRpYWwgZ2VuZSBleHByZXNzaW9uIGFuYWx5c2lzLgoKSWRlbnRpZmllciBtYXBwaW5nIHdhcyBwZXJmb3JtZWQgdXNpbmcgdGhlIHBhY2thZ2UgYmlvbWFSdCB3aXRoIGRhdGEgZnJvbSBFbnNlbWJsLiBUaGUgRW5zZW1ibCBnZW5lIElEcyBpbiB0aGUgb3JpZ2luYWwgZGF0YXNldCBhcmUgbWFwcGVkIHRvIHRoZSBjb3JyZXNwb25kaW5nIEhVR08gZ2VuZSBzeW1ib2xzLiBUaGUgZmluYWwgZGF0YXNldCBpbmNsdWRlZCAxMzcwNSBnZW5lcyB3aXRoIHVuaXF1ZSBpZGVudGlmaWVycy4KCiMgU2V0dXAKCkluIHRoaXMgc2VjdGlvbiwgd2UgaW1wb3J0IGFuZCBpbnN0YWxsIHRoZSBuZWNlc3NhcnkgcGFja2FnZXMgZm9yIHRoaXMgYXNzaWdubWVudCwgaW4gd2hpY2ggd2Ugd2lsbCBjb25kdWN0IGEgZGlmZmVyZW50aWFsIGV4cHJlc3Npb24gYW5hbHlzaXMgdXNpbmcgdGhlIG5vcm1hbGl6ZWQgZGF0YXNldCBhbmQgYSB0aHJlc2hvbGRlZCBvdmVyLXJlcHJlc2VudGF0aW9uIGFuYWx5c2lzLgoKYGBge3IgYTJfcGFja2FnZXMsIGVjaG89RkFMU0UsIG1lc3NhZ2U9RkFMU0UsIHJlc3VsdHM9J2hpZGUnfQppZiAoIXJlcXVpcmVOYW1lc3BhY2UoIm1hZ3JpdHRyIikpCiAgaW5zdGFsbC5wYWNrYWdlcygibWFncml0dHIiKQppZiAoIXJlcXVpcmVOYW1lc3BhY2UoImNpcmNsaXplIiwgcXVpZXRseSA9IFRSVUUpKQogICAgaW5zdGFsbC5wYWNrYWdlcygiY2lyY2xpemUiKQppZiAoIXJlcXVpcmVOYW1lc3BhY2UoIkNvbXBsZXhIZWF0bWFwIiwgcXVpZXRseSA9IFRSVUUpKQogICAgQmlvY01hbmFnZXI6Omluc3RhbGwoIkNvbXBsZXhIZWF0bWFwIikKaWYgKCFyZXF1aXJlTmFtZXNwYWNlKCJncHJvZmlsZXIyIiwgcXVpZXRseSA9IFRSVUUpKQogICAgQmlvY01hbmFnZXI6Omluc3RhbGwoImdwcm9maWxlcjIiKQoKIyBlZGdlUiBhbmQgb3RoZXIgcGFja2FnZXMgYXJlIGltcG9ydGVkIGluIEExLCB3aGljaCBpcyBzb3VyY2VkIGF0IHRoZSBiZWdpbm5pbmcgb2YgdGhlIG5vdGVib29rCgpsaWJyYXJ5KG1hZ3JpdHRyKQoKa25pdHI6Om9wdHNfY2h1bmskc2V0KG1lc3NhZ2UgPSBGQUxTRSkKYGBgCgojIERpZmZlcmVudGlhbCBFeHByZXNzaW9uIEFuYWx5c2lzIHVzaW5nIGVkZ2VSCgpJbiB0aGlzIHNlY3Rpb24sIHdlIGFyZSBnb2luZyB0byBwZXJmb3JtIGRpZmZlcmVudGlhbCBleHByZXNzaW9uIGFuYWx5c2lzLgoKTGV0IHVzIGZpcnN0IGV4YW1pbmUgdGhlIG5vcm1hbGl6ZWQgZGF0YS4KCmBgYHtyIG5vcm1hbGl6ZWRfZGF0YSwgZWNobz1GQUxTRSwgbWVzc2FnZT1GQUxTRSwgcmVzdWx0cz0naGlkZSd9CmtuaXRyOjprYWJsZShkWzE6MTAsMTo2XSRjb3VudHMsIGNhcHRpb24gPSAiTm9ybWFsaXplZCBnZW5lIGNvdW50cyIpICU+JSBrYWJsZUV4dHJhOjprYWJsZV9zdHlsaW5nKCJzdHJpcGVkIikKa25pdHI6OmthYmxlKGRbMToxMCwxOjZdJHNhbXBsZXMsIGNhcHRpb24gPSAiU2FtcGxlIGdyb3VwcyIpICU+JSBrYWJsZUV4dHJhOjprYWJsZV9zdHlsaW5nKCJzdHJpcGVkIikKYGBgCiMjIFdvcmtmbG93CgpXZSB3aWxsIGJlIGNhbGN1bGF0aW5nIGRpZmZlcmVudGlhbCBleHByZXNzaW9uIGZvbGxvd2luZyB0aGlzIGdlbmVyYWwgd29ya2Zsb3c6CgoxLiBDcmVhdGUgZGVpc25nIG1hdHJpeC4gV2Ugd2lsbCBlbnN1cmUgdGhhdCBhbGwgZmFjdG9ycyB0aGF0IGNvdWxkIGNvbnRyaWJ1dGUgdG8gZGlmZmVyZW50aWFsIGV4cHJlc3Npb24gaXMgYWNjb3VudGVkIGZvciBpbiB0aGUgZGVzaWduIG1hdHJpeC4KCjIuIFVzZSBhIG1lYW4tdmFyaWFuY2UgcGxvdCB0byBjb25maXJtIHRoYXQgdGhlIGRhdGEgZm9sbG93cyB0aGUgbmVnYXRpdmUgYmlub21pYWwgZGlzdHJpYnV0aW9uIGFzc3VtcHRpb24gZm9yIHVzaW5nIHRoZSBxdWFzaS1saWtlbGlob29kIG1vZGVsIGluIGVkZ2VSLgoKMy4gRml0IG91ciBkYXRhIHRvIHRoZSBtb2RlbCBhbmQgY2FsY3VsYXRlZCBwLXZhbHVlIGFuZCBjb3JyZWN0ZWQgcC12YWx1ZS4KCjQuIFVzZSBhIHRocmVzaG9sZCB0byBleHRyYWN0IGRpZmZlcmVudGlhbGx5IGV4cHJlc3NlZCBnZW5lcyB3aXRoIHN0YXRpc3RpY2FsbHkgc2lnbmlmaWNhbnQgZGlmZmVyZW5jZXMuCgo1LiBQbG90IGFuZCB2aXN1YWxpemUuCgojIyBDcmVhdGluZyB0aGUgRGVzaWduIE1hdHJpeAoKSW4gb3JkZXIgdG8gcGVyZm9ybSBzdGF0aXN0aWNhbCB0ZXN0aW5nLCB3ZSBuZWVkIGEgZGVzaWduIG1hdHJpeCB0aGUgZGVmaW5lcyBvdXIgbW9kZWwuIE5vdGljZSB0aGF0IGluIG91ciBkYXRhc2V0LCB0aGVyZSBhcmUgdGhyZWUgZmFjdG9yczogCgoxLiBUcmVhdG1lbnQgd2l0aCBDQkQKMi4gSW5mZWN0aW9uIHN0YXR1cyAoaW5mZWN0ZWQgb3Igbm90KQozLiBQYXRpZW50CgpIZW5jZSwgaWRlYWxseSwgd2Ugd291bGQgbGlrZSB0byBhY2NvdW50IGZvciBhbGwgdGhyZWUgZmFjdG9ycyBpbiBvdXIgZGVzaWduIG1hdHJpeC4KCmBgYHtyIGRlc2lnbl9tYXRyaXgsIGVjaG89RkFMU0UsIG1lc3NhZ2U9RkFMU0UsIHJlc3VsdHM9J2hpZGUnfQptb2RlbF9kZXNpZ24gPC0gbW9kZWwubWF0cml4KH4gc2FtcGxlcyRwYXRpZW50ICsgc2FtcGxlcyRjYmRfdHJlYXRtZW50ICsgc2FtcGxlcyRpbmZlY3RlZCkKbW9kZWxfZGVzaWduWyw0XSA8LSAhbW9kZWxfZGVzaWduWyw0XQpjb2xuYW1lcyhtb2RlbF9kZXNpZ24pWzRdIDwtICJzYW1wbGVzJGNiZF90cmVhdG1lbnRDQkQiCmtuaXRyOjprYWJsZShtb2RlbF9kZXNpZ24sIGNhcHRpb24gPSAiRGVzaWduIG1hdHJpeCIpICU+JQogIGthYmxlRXh0cmE6OmthYmxlX3N0eWxpbmcoInN0cmlwZWQiKQpgYGAKCiMjIERpc3RyaWJ1dGlvbiBvZiBEYXRhCgpGb3Igb3VyIGRvd25zdHJlYW0gYW5hbHlzaXMsIHdlIGFyZSBnb2luZyB0byB1c2UgZWRnZVIuIFdlIGNob3NlIGVkZ2VSIGJlY2F1c2UgaXQgaXMgc3BlY2lmaWNhbGx5IGRlc2lnbmVkIGZvciBSTkFTZXEgZGF0YS4gSG93ZXZlciwgb25lIGltcG9ydGFudCB1bmRlcmx5aW5nIGFzc3VtcHRpb24gZm9yIHVzaW5nIHRoZSBxdWFzaS1saWtlbGlob29kIG1vZGVsIGlzIHRoYXQgdGhlIGRhdGEgZm9sbG93cyBhIG5lZ2F0aXZlIGJpbm9taWFsIGRpc3RyaWJ1dGlvbi4gV2UgbmVlZCB0byB2ZXJpZnkgdGhhdCBvdXIgZGF0YXNldCBpbmRlZWQgbWVldHMgdGhhdCBhc3N1bXB0aW9uLgoKTGV0IHVzIHRoZSBjYWxjdWxhdGUgdGhlIGRpc3BlcnNpb24gYW5kIHBsb3QgdG8gdmlzdWFsaXplIHRoZSBtZWFuLXZhcmlhbmNlIHJlbGF0aW9uc2hpcC4KCmBgYHtyIGRpc3BlcnNpb25fY2FsYywgZWNobz1GQUxTRSwgbWVzc2FnZT1GQUxTRSwgcmVzdWx0cz0naGlkZSd9CmQgPC0gZWRnZVI6OkRHRUxpc3QoY291bnRzID0gbm9ybWFsaXplZF9jb3VudHNfYW5ub3RbLDM6bmNvbChub3JtYWxpemVkX2NvdW50c19hbm5vdCldLCBncm91cCA9IHNhbXBsZXMkY2JkX3RyZWF0bWVudCkKZCA8LSBlZGdlUjo6ZXN0aW1hdGVEaXNwKGQsIG1vZGVsX2Rlc2lnbikKYGBgCgpgYGB7ciBtZWFuX3Zhcl9wbG90fQplZGdlUjo6cGxvdE1lYW5WYXIoZCwKICAgICAgICAgICAgICAgICAgIHNob3cucmF3LnZhcnMgPSBUUlVFLAogICAgICAgICAgICAgICAgICAgc2hvdy50YWd3aXNlLnZhcnMgPSBUUlVFLAogICAgICAgICAgICAgICAgICAgTkJsaW5lID0gVFJVRSwKICAgICAgICAgICAgICAgICAgIHNob3cuYXZlLnJhdy52YXJzID0gVFJVRSwKICAgICAgICAgICAgICAgICAgIHNob3cuYmlubmVkLmNvbW1vbi5kaXNwLnZhcnMgPSBUUlVFLAogICAgICAgICAgICAgICAgICAgbWFpbiA9ICJNZWFuLVZhcmlhbmNlIFBsb3QgZm9yIFZhcmlhbmNlIGFuZCBEaXNwZXJzaW9uIG9mIE91ciBEYXRhIikKIyBkaXNwbGF5IGxlZ2VuZApsZWdlbmQoInRvcGxlZnQiLCAKICAgICAgIGxlZ2VuZD1jKCJSYXcgRGF0YSIsICJUYWd3aXNlIERpc3BlcnNpb24iLCAiQXZlcmFnZSBSYXcgVmFyaWFuY2VzIiwgCiAgICAgICAgICAgICAgICAiQmlubmVkIENvbW1vbiBEaXNwZXJzaW9uIiwgIk5lZ2F0aXZlIEJpbm9taWFsIExpbmUiKSwgCiAgICAgICBjb2wgPSBjKCJncmV5IiwgImxpZ2h0Ymx1ZSIsICJtYXJvb24iLCAicmVkIiwgImRvZGdlcmJsdWUyIiksIHBjaD1jKDEsMSw0LDQsTkEpLCBsdHk9YygwLDAsMCwwLDEpLCBsd2Q9YygxLDEsMSwxLDIpLCBjZXg9MC42KQpgYGAKCkFzIGRlbW9uc3RyYXRlZCBieSB0aGUgbWVhbi12YXJpYW5jZSBwbG90IGFib3ZlLCB3ZSBjYW4gc2VlIHRoYXQgdGhlIGRpc3BlcnNpb24gYW5kIHZhcmlhbmNlIG9mIG91ciBkYXRhIGluZGVlZCByb3VnaGx5IGZvbGxvd3MgdGhlIG5lZ2F0aXZlIGJpbm9taWFsIGRpc3RyaWJ1dGlvbi4KCiMjIEFuYWx5c2lzIFVzaW5nIGVkZ2VSCgpOb3csIHdlIGhhdmUgY3JlYXRlZCB0aGUgZGVzaWduIG1hdHJpeCBhbmQgdmVyaWZpZWQgdGhlIGFzc3VtcHRpb24gZm9yIHRoZSBkYXRhIHRvIGJlIG5lZ2F0aXZlLWJpbm9taWFsbHkgZGlzdHJpYnV0ZWQsIHdlIGNhbiBwcm9jZWVkIHRvIHRoZSBuZXh0IHN0YWdlIG9mIG91ciBhbmFseXNpcyBhbmQgcGVyZm9ybSBzdGF0aXN0aWNhbCB0ZXN0aW5nIGFuZCBjb3JyZWN0aW9ucyB0byBlbnN1cmUgdGhhdCB3ZSBvbmx5IGdldCBzaWduaWZpY2FudGx5IGRpZmZlcmVudGlhbGx5IGV4cHJlc3NlZCBnZW5lcy4gV2UgdXNlZCB0aGUgcXVhc2ktbGlrZWxpaG9vZCBtb2RlbHMgc2luY2Ugb3VyIGRhdGFzZXQgaXMgZnJvbSBhbiBSTkFTZXEgZXhwZXJpbWVudCBhbmQgcXVhc2ktbGlrZWxpaG9vZCBtb2RlbHMgYXJlIGJlc3Qgc3VpdGVkIHRvIGhhbmRsZSBSTkFTZXEgZGF0YS4KCmBgYHtyIGZpdF9xbCwgZWNobz1GQUxTRSwgbWVzc2FnZT1GQUxTRSwgcmVzdWx0cz0naGlkZSd9CmZpdCA8LSBlZGdlUjo6Z2xtUUxGaXQoZCwgbW9kZWxfZGVzaWduKQpgYGAKCk9uY2Ugd2UgaGF2ZSBmaXQgdGhlIG1vZGVsLCB3ZSBjYW4gcHJvY2VlZCB0byBjYWxjdWxhdGUgZGlmZmVyZW50aWFsIGV4cHJlc3Npb24uIFJlY2FsbCB0aGF0IG91ciBnb2FsIGlzIHRvIHZlcmlmeSB0aGUgcm9sZSBvZiBjYW5uYWJpZGlvbCBpbiBhZmZlY3RpbmcgdGhlIHJlcGxpY2F0aW9uIGFiaWxpdHkgb2YgU0FSUy1Db1YtMiwgc28gd2Ugd2lsbCBiZSB1c2luZyBgY2JkX3RyZWF0bWVudGAgYXMgdGhlIGNvbnRyYXN0LgoKYGBge3IgdGVzdF9xbCwgZWNobz1GQUxTRSwgbWVzc2FnZT1GQUxTRSwgcmVzdWx0cz0naGlkZSd9CnFsZiA8LSBlZGdlUjo6Z2xtUUxGVGVzdChmaXQsIGNvZWYgPSAnc2FtcGxlcyRjYmRfdHJlYXRtZW50Q0JEJykKcWxmX2RpZmZfZXhwIDwtIGVkZ2VSOjp0b3BUYWdzKHFsZiwgc29ydC5ieSA9ICJQVmFsdWUiLCBuID0gbnJvdyhub3JtYWxpemVkX2NvdW50c19hbm5vdCkpCmtuaXRyOjprYWJsZShxbGZfZGlmZl9leHBbMToxMCxdJHRhYmxlLCB0eXBlPSJodG1sIiwgZGlnaXRzID0gMjAsIGNhcHRpb24gPSAiVG9wIGRpZmZlcmVudGlhbGx5IGV4cHJlc3NlZCBnZW5lcyIpICU+JQogIGthYmxlRXh0cmE6OmthYmxlX3N0eWxpbmcoInN0cmlwZWQiKQpgYGAKCldlIGNhbiBleGFtaW5lIHRoZSBudW1iZXIgb2YgZ2VuZXMgcGFzcyB0aGUgdGhyZXNob2xkIGFuZCBjb3JyZWN0aW9uLiBXZSBhcmUgdXNpbmcgMC4wNSBhcyB0aGUgdGhyZXNob2xkIGZvciBwLXZhbHVlIGFzIGl0IGlzIGNvbW1vbmx5IHVzZWQgaW4gcHJhY3RpY2UuCgpgYGB7ciBjb3VudF9kaWZmX3B2YWwsIGVjaG89RkFMU0UsIG1lc3NhZ2U9RkFMU0UsIHJlc3VsdHM9J2hpZGUnfQojIG51bWJlciBvZiBnZW5lcyB0aGF0IHBhc3NlZCB0aGUgdGhyZXNob2xkCnN1bShxbGZfZGlmZl9leHAkdGFibGUkUFZhbHVlIDwgMC4wNSkKYGBgCmBgYHtyIGNvdW50X2RpZmZfZmRyLCBlY2hvPUZBTFNFLCBtZXNzYWdlPUZBTFNFLCByZXN1bHRzPSdoaWRlJ30KIyBudW1iZXIgb2YgZ2VuZXMgdGhhdCBwYXNzZWQgY29ycmVjdGlvbgpzdW0ocWxmX2RpZmZfZXhwJHRhYmxlJEZEUiA8IDAuMDUpCmBgYAoKVGhlIHRocmVzaG9sZCBvZiAwLjA1IGdpdmVzIHVzIHF1aXRlIGEgbG90IG9mIGdlbmVzLCBpbiBvcmRlciB0byBnZXQgbW9yZSBtZWFuaW5nZnVsIGhpdHMgaW4gdGhlIGRvd25zdHJlYW0gZ2VuZSBlbnJpY2htZW50IGFuYWx5c2lzLCB3ZSB3aWxsIG1ha2UgdGhlIHRoZXJzaG9sZCBtb3JlIHN0cmluZ2VudC4KCmBgYHtyIGNvdW50X2RpZmZfcHZhbF9zdHJpbmdlbnQsIGVjaG89RkFMU0UsIG1lc3NhZ2U9RkFMU0UsIHJlc3VsdHM9J2hpZGUnfQojIG51bWJlciBvZiBnZW5lcyB0aGF0IHBhc3NlZCB0aGUgdGhyZXNob2xkCnN1bShxbGZfZGlmZl9leHAkdGFibGUkUFZhbHVlIDwgMC4wMSAmIGFicyhxbGZfZGlmZl9leHAkdGFibGUkbG9nRkMpID4gMS41KQpgYGAKYGBge3IgY291bnRfZmRyX3N0cmluZ2VudCwgZWNobz1GQUxTRSwgbWVzc2FnZT1GQUxTRSwgcmVzdWx0cz0naGlkZSd9CiMgbnVtYmVyIG9mIGdlbmVzIHRoYXQgcGFzc2VkIGNvcnJlY3Rpb24Kc3VtKHFsZl9kaWZmX2V4cCR0YWJsZSRGRFIgPCAwLjAxICYgYWJzKHFsZl9kaWZmX2V4cCR0YWJsZSRsb2dGQykgPiAxLjUpCmBgYAoKIyMgVmlzdWFsaXphdGlvbiBvZiBEaWZmZXJlbnRpYWxseSBFeHByZXNzZWQgR2VuZXMKCk5vdyB3ZSBjYW4gcmV0cmlldmUgdGhlIGxpc3Qgb2YgZGlmZmVyZW50aWFsIGV4cHJlc3NlZCBnZW5lcyBhbmQgdmlzdWFsaXplIHVzaW5nIGRpZmZlcmVudCBwbG90cy4gV2Ugd2lsbCBmaXJzdCBwbG90IHRoZW0gb24gYSB2b2xjYW5vIHBsb3QuIEVhY2ggZ2VuZSBpcyByZXByZXNlbnRlZCBieSBhIHBvaW50IGluIHRoZSBwbG90LiBUaGUgaG9yaXpvbnRhbCBheGlzIG9mIHRoZSBwbG90IGlzIHRoZSAkXGxvZ18yJCBmb2xkIGNoYW5nZSBhbmQgdGhlIHZlcnRpY2FsIGF4aXMgaXMgdGhlICQtXGxvZ197MTB9cCQgd2hpY2ggaW5kaWNhdGVzIHRoZSBzdGF0aXN0aWNhbCBzaWduaWZpY2FuY2Ugb2YgZWFjaCBnZW5lIChob3cgbGlrZWx5IHRoZSBkaWZmZXJlbnRpYWwgaXMgZHVlIHRvIGFjdHVhbCBiaW9sb2dpY2FsIHZhcmlhdGlvbikuCgpgYGB7ciB2b2xjYW5vX3Bsb3QsIGVjaG89RkFMU0UsIG1lc3NhZ2U9RkFMU0UsIHJlc3VsdHM9J2hpZGUnfQp2b2xjYW5vX2NvbG9yX3BhbGV0dGUgPSByZXAoJ2dyYXknLCB0aW1lcyA9IG5yb3cocWxmX2RpZmZfZXhwJHRhYmxlKSkKdm9sY2Fub19jb2xvcl9wYWxldHRlW3FsZl9kaWZmX2V4cCR0YWJsZSRsb2dGQyA8IDAgJiBxbGZfZGlmZl9leHAkdGFibGUkRkRSIDwgMC4wMSAmIGFicyhxbGZfZGlmZl9leHAkdGFibGUkbG9nRkMpID4gMS41XSA8LSAnYmx1ZScKdm9sY2Fub19jb2xvcl9wYWxldHRlW3FsZl9kaWZmX2V4cCR0YWJsZSRsb2dGQyA+IDAgJiBxbGZfZGlmZl9leHAkdGFibGUkRkRSIDwgMC4wMSAmIGFicyhxbGZfZGlmZl9leHAkdGFibGUkbG9nRkMpID4gMS41XSA8LSAncmVkJwoKcGxvdChxbGZfZGlmZl9leHAkdGFibGUkbG9nRkMsIAogICAgIC1sb2cocWxmX2RpZmZfZXhwJHRhYmxlJFBWYWx1ZSwgYmFzZT0xMCksIAogICAgIGNvbCA9IHZvbGNhbm9fY29sb3JfcGFsZXR0ZSwKICAgICB4bGFiID0gImxvZzIgZm9sZCBjaGFuZ2UiLAogICAgIHlsYWIgPSAiLWxvZzEwIHAiLAogICAgIG1haW4gPSAiVm9sY2FubyBwbG90IHNob3dpbmcgdXByZWd1bGF0ZWQgYW5kIGRvd25yZWd1bGF0ZWQgZ2VuZXMiCiAgICApCgpsZWdlbmQoInRvcHJpZ2h0IiwgbGVnZW5kPWMoIkRvd25yZWd1bGF0ZWQgaW4gQ0JEIHRyZWF0ZWQgY2VsbHMiLCJVcHJlZ3VsYXRlZCBpbiBDQkQgdHJlYXRlZCBjZWxscyIsICJOb3Qgc2lnbmlmaWNhbnQiKSxmaWxsID0gYygiYmx1ZSIsICJyZWQiLCAiZ3JleSIpLCBjZXggPSAwLjUpCmBgYAoKTmV4dCwgd2Ugd2lsbCB2aXN1YWxpemUgdGhlIHVwcmVndWxhdGVkIGFuZCBkb3ducmVndWxhdGVkIGdlbmVzIGFjcm9zcyBkaWZmZXJlbnQgdGVzdCBjb25kaXRpb25zIHVzaW5nIGEgaGVhdG1hcC4KCmBgYHtyIGhlYXRtYXAsIGVjaG89RkFMU0UsIG1lc3NhZ2U9RkFMU0UsIHJlc3VsdHM9J2hpZGUnfQpkaWZmX2V4cF9sc3QgPC0gcWxmX2RpZmZfZXhwJHRhYmxlW3FsZl9kaWZmX2V4cCR0YWJsZSRGRFIgPCAwLjAxICYgYWJzKHFsZl9kaWZmX2V4cCR0YWJsZSRsb2dGQyksXQpkaWZmX2V4cF9sc3QkaGduY19zeW1ib2wgPC0gcm93bmFtZXMoZGlmZl9leHBfbHN0KQoKIyBub3JtYWxpemVkIGNvdW50cyBvZiBkaWZmZXJlbnRpYWxseSBleHByZXNzZWQgZ2VuZXMKbWF0X2NvdW50X25vcm1hbGl6ZWRfZGlmZiA8LSBub3JtYWxpemVkX2NvdW50c19hbm5vdFtkaWZmX2V4cF9sc3QkaGduY19zeW1ib2wsIDM6bmNvbChub3JtYWxpemVkX2NvdW50c19hbm5vdCldCiMgcmVzY2FsZSB0aGUgY291bnRzCm1hdF9jb3VudF9ub3JtYWxpemVkX2RpZmYgPC0gdChzY2FsZSh0KG1hdF9jb3VudF9ub3JtYWxpemVkX2RpZmYpKSkKaGVhdG1hcF9jb2xvcl9wYWxldHRlIDwtIGNpcmNsaXplOjpjb2xvclJhbXAyKGMobWluKG1hdF9jb3VudF9ub3JtYWxpemVkX2RpZmYpLCAwLCBtYXgobWF0X2NvdW50X25vcm1hbGl6ZWRfZGlmZikpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYygiYmx1ZSIsICJ3aGl0ZSIsICJyZWQiKSkKQ29tcGxleEhlYXRtYXA6OkhlYXRtYXAoYXMubWF0cml4KG1hdF9jb3VudF9ub3JtYWxpemVkX2RpZmYpLAogICAgICAgICAgICAgICAgICAgICAgICBuYW1lID0gInNjYWxlZCBub3JtYWxpemVkIGNvdW50IiwKICAgICAgICAgICAgICAgICAgICAgICAgY2x1c3Rlcl9yb3dzID0gVFJVRSwKICAgICAgICAgICAgICAgICAgICAgICAgY2x1c3Rlcl9jb2x1bW5zID0gVFJVRSwgCiAgICAgICAgICAgICAgICAgICAgICAgIHNob3dfcm93X2RlbmQgPSBGQUxTRSwgCiAgICAgICAgICAgICAgICAgICAgICAgIHNob3dfY29sdW1uX2RlbmQgPSBGQUxTRSwgCiAgICAgICAgICAgICAgICAgICAgICAgIGNvbCA9IGhlYXRtYXBfY29sb3JfcGFsZXR0ZSwgCiAgICAgICAgICAgICAgICAgICAgICAgIHNob3dfY29sdW1uX25hbWVzID0gVFJVRSwgCiAgICAgICAgICAgICAgICAgICAgICAgIHNob3dfcm93X25hbWVzID0gRkFMU0UsIAogICAgICAgICAgICAgICAgICAgICAgICBzaG93X2hlYXRtYXBfbGVnZW5kID0gVFJVRSwKICAgICAgICAgICAgICAgICAgICAgICAgY29sdW1uX3RpdGxlID0gIlNhbXBsZXMiLAogICAgICAgICAgICAgICAgICAgICAgICByb3dfdGl0bGUgPSAiR2VuZXMiLAogICAgICAgICAgICAgICAgICAgICAgICB1c2VfcmFzdGVyID0gVFJVRSkKYGBgCgojIyBEaXNjdXNzaW9uCgoxLiBJbml0aWFsbHksIEkgdXNlZCB0aGUgcC12YWx1ZSBvZiAwLjA1IGFzIGl0IGlzIHdpZGVseSB1c2VkIGluIHByYWN0aWNlLiBUaGlzIGdpdmVzIHVzIDU1MDEgZ2VuZXMgcHJpb3IgdG8gY29ycmVjdGlvbi4gVGhpcyBpcyBxdWl0ZSBhIGxhcmdlIG51bWJlciBvZiBnZW5lcywgc28gd2UgY2hhbmdlZCB0aGUgcC12YWx1ZSB0aHJlc2hvbGQgdG8gMC4wMSB0byBsaW1pdCB0aGUgbnVtYmVyIG9mIGdlbmVzIGluY2x1ZGVkLiBXZSBmdXJ0aGVyIGFkZGVkIHRoZSBjcml0ZXJpYSB0aGF0IGEgZ2VuZSBtdXN0IGhhdmUgYW4gYWJzb2x1dGUgbG9nIGZvbGQgY2hhbmdlIGdyZWF0ZXIgdGhhbiAxLjUuIEJ5IGRvaW5nIHNvLCB3ZSBhcmUgY29udHJhaW5pbmcgb3Vyc2VsdmVzIHRvIG9ubHkgZ2V0IHRoZSBnZW5lcyB0aGF0IGFyZSBoaWdobHkgZGlmZmVyZW50aWFsbHkgZXhwcmVzc2VkIHdpdGggaGlnaCBzdGF0aXN0aWNhbCBzaWduaWZpY2FuY2UuCgoyLiBGb3IgY29ycmVjdGlvbiwgd2UgdXNlZCBCZW5qYW1pbmktSG9jaGJlcmcuIFRoZSB0d28gbWFpbiBtZXRob2RzIGRpc2N1c3NlZCBmb3IgY29ycmVjdGluZyBmYW1pbHktd2lzZSBmYWxzZSBkaXNjb3ZlcnkgcmF0ZSBhcmUgQm9uZmVycm9uaSBhbmQgQmVuamFtaW5pLUhvY2hiZXJnIGNvcnJlY3Rpb24uIFdlIHdhbnQgdG8gZ2V0IG1lYW5pbmdmdWwgaGl0cyB3aXRob3V0IGV4Y2x1ZGluZyBzdGF0aXN0aWNhbGx5IHNpZ25pZmljYW50IG9uZXMuIEJvbmZlcnJvbmkncyBtZXRob2QgaXMgb3Zlcmx5IHN0cmluZ2VudCBzbyBpdCBpcyBub3QgcXVpdGUgc3VpdGFibGUgZm9yIG91ciBwdXJwb3Nlcy4gVXNpbmcgQmVuamFtaW5pLUhvY2hiZXJnIHdpbGwgZ2l2ZSB1cyBhIHJpY2hlciBzZXQgb2YgZ2VuZXMgdGhhdCB3ZSBjYW4gdXNlIGZvciBkb3duc3RyZWFtIGFuYWx5c2lzLgoKMy4gVm9sY2FubyBwbG90IHNob3duIGFib3ZlLiBOb3RlIHRoYXQgd2UgYWxzbyBhcHBsaWVkIHRoZSByZXN0cmljdGlvbiB0aGF0IG9ubHkgZ2VuZXMgd2l0aCBhYm9zbHV0ZSBsb2cgZm9sZCBjaGFuZ2UgZ3JlYXRlciB0aGFuIDEuNSBhcmUgdG8gYmUgaW5jbHVkZWQuCgo0LiBUaGVyZSBpcyBzaWduaWZpY2FudCBjbHVzdGVyaW5nIHdpdGhpbiBjb25kaXRpb25zLiBUaGlzIHN1Z2dlc3RzIHRoYXQgdGhlIHRlc3QgY29uZGl0aW9uIChDQkQgdi5zLiBubyBDQkQpIGRvZXMgaGF2ZSBhIHNpZ25pZmljYW50IGVmZmVjdCBvbiBnZW5lIGV4cHJlc3Npb25zLgoKIyBUaHJlc2hvbGRlZCBPdmVycmVwcmVzZW50YXRpb24gQW5hbHlzaXMgdXNpbmcgZzpQcm9maWxlcgoKRm9yIHRoZSBmaW5hbCBwYXJ0IG9mIHRoaXMgYXNzaWdubWVudCwgd2Ugd2lsbCBwZXJmb3JtIGEgdGhyZXNob2xkZWQgb3ZlcnJlcHJlc2VudGF0aW9uIGFuYWx5c2lzIHVzaW5nIGc6UHJvZmlsZXIuIEluIHRoZSBwcmV2aW91cyBzZWN0aW9uLCB3ZSBoYXZlIGNvbXBpbGVkIGEgbGlzdCBvZiBkaWZmZXJlbnRpYWxseSBleHByZXNzZWQgZ2VuZXMuIEhlcmUsIHdlIHdhbnQgdG8gZnVydGhlciBkaXZpZGUgdGhlbSBpbnRvIHVwcmVndWxhdGVkIGFuZCBkb3ducmVndWxhdGVkIGdlbmVzLgoKYGBge3Igc3BsaXRfdXBkb3ducmVndWxhdGVkfQp1cHJlZ3VsYXRlZF9nZW5lX2xzdCA8LSBkaWZmX2V4cF9sc3RbZGlmZl9leHBfbHN0JGxvZ0ZDID4gMCxdCmRvd25yZWd1bGF0ZWRfZ2VuZV9sc3QgPC0gZGlmZl9leHBfbHN0W2RpZmZfZXhwX2xzdCRsb2dGQyA8IDAsXQpgYGAKCldlIHVzZSB0aGUgUiBwYWNrYWdlIGZvciBnOlByb2ZpbGVyIHRvIHBlcmZvcm0gdGhlIGdlbmUgZW5yaWNobWVudCBhbmFseXNpcy4gRm9yIGNvcnJlY3Rpb24sIHdlIHVzZWQgRkRSIGFzIGl0IGlzIGxlc3Mgc3RyaW5nZW50IHRoYW4gQm9uZmVycm9uaSBhbmQgaXMgaW50cm9kdWNlZCBhcyB0aGUgcHJlZmVycmVkIGNvcnJlY3Rpb24gbWV0aG9kIGluIGNsYXNzLiBXZSB1c2VkIEdPIEJpb2xvZ2ljYWwgUHJvY2VzcywgR08gTW9sZWN1bGFyIEZ1bmN0aW9uLCBhbmQgS0VHRyBhcyB0aG9zZSBhcmUgdGhlIG9uZXMgdXNlZCBieSB0aGUgYXV0aG9yIG9mIHRoZSBvcmlnaW5hbCBwdWJsaWNhdGlvbi4gRm9yIGEgbW9yZSBkZXRhaWxlZCBvdmVydmlldyBvZiB0aGUgd29ya2Zsb3csIHBsZWFzZSByZWZlciB0byB0aGUgRGlzY3Vzc2lvbiBzdWJzZWN0aW9uIGxvY2F0ZWQgYXQgdGhlIGVuZCBvZiB0aGlzIHNlY3Rpb24uCgojIyBVcHJlZ3VsYXRlZCBHZW5lcwoKYGBge3IgZ3Byb2ZpbGVyX3VwLCBlY2hvPUZBTFNFLCBtZXNzYWdlPUZBTFNFLCByZXN1bHRzPSdoaWRlJ30KdXBfdG9wX3Rlcm1zX2FsbCA8LSBncHJvZmlsZXIyOjpnb3N0KHF1ZXJ5ID0gcm93bmFtZXModXByZWd1bGF0ZWRfZ2VuZV9sc3QpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9yZ2FuaXNtID0gImhzYXBpZW5zIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBleGNsdWRlX2llYSA9IFRSVUUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb3JyZWN0aW9uX21ldGhvZCA9ICJmZHIiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc291cmNlcyA9IGMoIkdPOkJQIiwgIkdPOk1GIiwgIktFR0ciKSkKCnVwX3RvcF90ZXJtcyA8LSBkYXRhLmZyYW1lKAogIHRlcm1fbmFtZSA9IHVwX3RvcF90ZXJtc19hbGwkcmVzdWx0JHRlcm1fbmFtZVt1cF90b3BfdGVybXNfYWxsJHJlc3VsdCR0ZXJtX3NpemUgPCA1MDAgJgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHVwX3RvcF90ZXJtc19hbGwkcmVzdWx0JHRlcm1fc2l6ZSA+IDJdLAogIHRlcm1faWQgPSB1cF90b3BfdGVybXNfYWxsJHJlc3VsdCR0ZXJtX2lkW3VwX3RvcF90ZXJtc19hbGwkcmVzdWx0JHRlcm1fc2l6ZSA8IDUwMCAmCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB1cF90b3BfdGVybXNfYWxsJHJlc3VsdCR0ZXJtX3NpemUgPiAyXSwKICBzb3VyY2UgPSB1cF90b3BfdGVybXNfYWxsJHJlc3VsdCRzb3VyY2VbdXBfdG9wX3Rlcm1zX2FsbCRyZXN1bHQkdGVybV9zaXplIDwgNTAwICYKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB1cF90b3BfdGVybXNfYWxsJHJlc3VsdCR0ZXJtX3NpemUgPiAyXQopCgprbml0cjo6a2FibGUodXBfdG9wX3Rlcm1zWzE6MTAsXSwgY2FwdGlvbiA9ICJUb3AgZ2VuZXNldHMgdXNpbmcgbGlzdCBvZiB1cHJlZ3VsYXRlZCBnZW5lcyIpICU+JSBrYWJsZUV4dHJhOjprYWJsZV9zdHlsaW5nKCJzdHJpcGVkIikKYGBgCkZvciBjb250ZXh0LCBsZXQncyBleGFtaW5lIHRoZSB0b3AgdGVybSBmcm9tIGVhY2ggZGF0YSBzb3VyY2UuCgpgYGB7ciB1cF90b3BfdGVybV9wZXJfY2F0ZWdvcnksIGVjaG89RkFMU0UsIG1lc3NhZ2U9RkFMU0UsIHJlc3VsdHM9J2hpZGUnfQprbml0cjo6a2FibGUocmJpbmQodXBfdG9wX3Rlcm1zW3VwX3RvcF90ZXJtcyRzb3VyY2UgPT0gIkdPOkJQIixdWzEsXSwKICAgICAgICAgICAgICAgICAgIHVwX3RvcF90ZXJtc1t1cF90b3BfdGVybXMkc291cmNlID09ICJHTzpNRiIsXVsxLF0sCiAgICAgICAgICAgICAgICAgICB1cF90b3BfdGVybXNbdXBfdG9wX3Rlcm1zJHNvdXJjZSA9PSAiS0VHRyIsXVsxLF0pLAogICAgICAgICAgICAgY2FwdGlvbiA9ICJUb3AgdGVybXMgZnJvbSBlYWNoIGRhdGEgc291cmNlIHVzaW5nIGxpc3Qgb2YgdXByZWd1bGF0ZWQgZ2VuZXMiKSAlPiUKICBrYWJsZUV4dHJhOjprYWJsZV9zdHlsaW5nKCJzdHJpcGVkIikKYGBgCldlIGNhbiB2aXN1YWxpemUgdGhlIGRpc3RyaWJ1dGlvbiBvZiB0b3AgdGVybXMgZnJvbSBlYWNoIGRhdGEgc291cmNlIHVzaW5nIGFuIE1hbmhhdHRhbiBwbG90LiBUaGlzIGlzIHRoZSBkaXN0cmlidXRpb24gb2YgdGVybXMgcHJpb3IgdG8gcmVtb3ZpbmcgbGFyZ2UgdGVybXMgd2l0aCBvdmVyIDUwMCBnZW5lcy4KCmBgYHtyIHVwX2Rpc3RfcGxvdH0KZ3Byb2ZpbGVyMjo6Z29zdHBsb3QodXBfdG9wX3Rlcm1zX2FsbCkgJT4lIHBsb3RseTo6bGF5b3V0KHRpdGxlID0gIk1hbmhhdHRhbiBwbG90IHNob3dpbmcgZGlzdHJpYnV0aW9uIG9mIHRlcm1zIFxuZnJvbSBlYWNoIGRhdGEgc291cmNlIHVzaW5nIGxpc3Qgb2YgdXByZWd1bGF0ZWQgZ2VuZXMiLCBmb250ID0gbGlzdChzaXplID0gMTApKQpgYGAKCmBgYHtyIGNvdW50X3VwX3RvcF90ZXJtcywgZWNobz1GQUxTRSwgbWVzc2FnZT1GQUxTRSwgcmVzdWx0cz0naGlkZSd9Cmxlbmd0aCh1cF90b3BfdGVybXMkdGVybV9uYW1lKQpgYGAKCiMjIERvd25yZWd1bGF0ZWQgR2VuZXMKCldlIGRvIHRoZSBzYW1lIGZvciB0aGUgZG93bnJlZ3VhbHRlZCBnZW5lcy4KCmBgYHtyIGdwcm9maWxlcl9kb3duLCBlY2hvPUZBTFNFLCBtZXNzYWdlPUZBTFNFLCByZXN1bHRzPSdoaWRlJ30KZG93bl90b3BfdGVybXNfYWxsIDwtIGdwcm9maWxlcjI6Omdvc3QocXVlcnkgPSByb3duYW1lcyhkb3ducmVndWxhdGVkX2dlbmVfbHN0KSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvcmdhbmlzbSA9ICJoc2FwaWVucyIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXhjbHVkZV9pZWEgPSBUUlVFLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29ycmVjdGlvbl9tZXRob2QgPSAiZmRyIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNvdXJjZXMgPSBjKCJHTzpCUCIsICJHTzpNRiIsICJLRUdHIikpCgpkb3duX3RvcF90ZXJtcyA8LSBkYXRhLmZyYW1lKAogIHRlcm1fbmFtZSA9IGRvd25fdG9wX3Rlcm1zX2FsbCRyZXN1bHQkdGVybV9uYW1lW2Rvd25fdG9wX3Rlcm1zX2FsbCRyZXN1bHQkdGVybV9zaXplIDwgNTAwICYKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRvd25fdG9wX3Rlcm1zX2FsbCRyZXN1bHQkdGVybV9zaXplID4gMl0sCiAgdGVybV9pZCA9IGRvd25fdG9wX3Rlcm1zX2FsbCRyZXN1bHQkdGVybV9pZFtkb3duX3RvcF90ZXJtc19hbGwkcmVzdWx0JHRlcm1fc2l6ZSA8IDUwMCAmCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRvd25fdG9wX3Rlcm1zX2FsbCRyZXN1bHQkdGVybV9zaXplID4gMl0sCiAgc291cmNlID0gZG93bl90b3BfdGVybXNfYWxsJHJlc3VsdCRzb3VyY2VbZG93bl90b3BfdGVybXNfYWxsJHJlc3VsdCR0ZXJtX3NpemUgPCA1MDAgJgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZG93bl90b3BfdGVybXNfYWxsJHJlc3VsdCR0ZXJtX3NpemUgPiAyXQopCgprbml0cjo6a2FibGUoZG93bl90b3BfdGVybXNbMToxMCxdLCBjYXB0aW9uID0gIlRvcCBnZW5lc2V0cyB1c2luZyBsaXN0IG9mIGRvd25yZWd1bGF0ZWQgZ2VuZXMiKSAlPiUga2FibGVFeHRyYTo6a2FibGVfc3R5bGluZygic3RyaXBlZCIpCmBgYAoKYGBge3IgZG93bl90b3BfdGVybV9wZXJfY2F0ZWdvcnksIGVjaG89RkFMU0UsIG1lc3NhZ2U9RkFMU0UsIHJlc3VsdHM9J2hpZGUnfQprbml0cjo6a2FibGUocmJpbmQoZG93bl90b3BfdGVybXNbZG93bl90b3BfdGVybXMkc291cmNlID09ICJHTzpCUCIsXVsxLF0sCiAgICAgICAgICAgICAgICAgICBkb3duX3RvcF90ZXJtc1tkb3duX3RvcF90ZXJtcyRzb3VyY2UgPT0gIkdPOk1GIixdWzEsXSwKICAgICAgICAgICAgICAgICAgIGRvd25fdG9wX3Rlcm1zW2Rvd25fdG9wX3Rlcm1zJHNvdXJjZSA9PSAiS0VHRyIsXVsxLF0pLAogICAgICAgICAgICAgY2FwdGlvbiA9ICJUb3AgdGVybXMgZnJvbSBlYWNoIGRhdGEgc291cmNlIHVzaW5nIGxpc3Qgb2YgZG93bnJlZ3VsYXRlZCBnZW5lcyIpICU+JQogIGthYmxlRXh0cmE6OmthYmxlX3N0eWxpbmcoInN0cmlwZWQiKQpgYGAKUGxvdCB0aGUgTWFuaGF0dGFuIHBsb3Qgc2hvd2luZyBkaXN0cmlidXRpb24gb2YgdGVybXMgZnJvbSBlYWNoIGRhdGEgc291cmNlIHVzaW5nIGxpc3Qgb2YgZG93bnJlZ3VsYXRlZCBnZW5lcy4KCmBgYHtyIGRvd25fZGlzdF9wbG90fQpncHJvZmlsZXIyOjpnb3N0cGxvdChkb3duX3RvcF90ZXJtc19hbGwpICU+JSBwbG90bHk6OmxheW91dCh0aXRsZSA9ICJNYW5oYXR0YW4gcGxvdCBzaG93aW5nIGRpc3RyaWJ1dGlvbiBvZiB0ZXJtc1xuIGZyb20gZWFjaCBkYXRhIHNvdXJjZSB1c2luZyBsaXN0IG9mIGRvd25yZWd1bGF0ZWQgZ2VuZXMiLCBmb250ID0gbGlzdChzaXplID0gMTApKQpgYGAKCmBgYHtyIGNvdW50X2Rvd25fdG9wX3Rlcm1zLCBlY2hvPUZBTFNFLCBtZXNzYWdlPUZBTFNFLCByZXN1bHRzPSdoaWRlJ30KbGVuZ3RoKGRvd25fdG9wX3Rlcm1zJHRlcm1fbmFtZSkKYGBgCgojIyBBbGwgRGlmZmVyZW50aWFsbHkgRXhwcmVzc2VkIEdlbmVzCgpGaW5hbGx5LCBmb3IgYWxsIGRpZmZlcmVudGlhbGx5IGV4cHJlc3NlZCBnZW5lcy4KCmBgYHtyIGdwcm9maWxlcl9vdmVyYWxsLCBlY2hvPUZBTFNFLCBtZXNzYWdlPUZBTFNFLCByZXN1bHRzPSdoaWRlJ30KdG9wX3Rlcm1zX2FsbCA8LSBncHJvZmlsZXIyOjpnb3N0KHF1ZXJ5ID0gcm93bmFtZXMoZGlmZl9leHBfbHN0KSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvcmdhbmlzbSA9ICJoc2FwaWVucyIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXhjbHVkZV9pZWEgPSBUUlVFLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29ycmVjdGlvbl9tZXRob2QgPSAiZmRyIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNvdXJjZXMgPSBjKCJHTzpCUCIsICJHTzpNRiIsICJLRUdHIikpCgp0b3BfdGVybXMgPC0gZGF0YS5mcmFtZSgKICB0ZXJtX25hbWUgPSB0b3BfdGVybXNfYWxsJHJlc3VsdCR0ZXJtX25hbWVbdG9wX3Rlcm1zX2FsbCRyZXN1bHQkdGVybV9zaXplIDwgNTAwICYKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0b3BfdGVybXNfYWxsJHJlc3VsdCR0ZXJtX3NpemUgPiAyXSwKICB0ZXJtX2lkID0gdG9wX3Rlcm1zX2FsbCRyZXN1bHQkdGVybV9pZFt0b3BfdGVybXNfYWxsJHJlc3VsdCR0ZXJtX3NpemUgPCA1MDAgJgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdG9wX3Rlcm1zX2FsbCRyZXN1bHQkdGVybV9zaXplID4gMl0sCiAgc291cmNlID0gdG9wX3Rlcm1zX2FsbCRyZXN1bHQkc291cmNlW3RvcF90ZXJtc19hbGwkcmVzdWx0JHRlcm1fc2l6ZSA8IDUwMCAmCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdG9wX3Rlcm1zX2FsbCRyZXN1bHQkdGVybV9zaXplID4gMl0KKQoKa25pdHI6OmthYmxlKHRvcF90ZXJtc1sxOjEwLF0sIGNhcHRpb24gPSAiVG9wIGdlbmVzZXRzIHVzaW5nIGxpc3Qgb2YgYWxsIGRpZmZlcmVudGlhbGx5IGV4cHJlc3NlZCBnZW5lcyIpICU+JSBrYWJsZUV4dHJhOjprYWJsZV9zdHlsaW5nKCJzdHJpcGVkIikKYGBgCgpgYGB7ciB0b3BfdGVybV9wZXJfY2F0ZWdvcnksIGVjaG89RkFMU0UsIG1lc3NhZ2U9RkFMU0UsIHJlc3VsdHM9J2hpZGUnfQprbml0cjo6a2FibGUocmJpbmQodG9wX3Rlcm1zW3RvcF90ZXJtcyRzb3VyY2UgPT0gIkdPOkJQIixdWzEsXSwKICAgICAgICAgICAgICAgICAgIHRvcF90ZXJtc1t0b3BfdGVybXMkc291cmNlID09ICJHTzpNRiIsXVsxLF0sCiAgICAgICAgICAgICAgICAgICB0b3BfdGVybXNbdG9wX3Rlcm1zJHNvdXJjZSA9PSAiS0VHRyIsXVsxLF0pLAogICAgICAgICAgICAgY2FwdGlvbiA9ICJUb3AgdGVybXMgZnJvbSBlYWNoIGRhdGEgc291cmNlIHVzaW5nIGxpc3Qgb2YgYWxsIGRpZmZlcmVudGlhbGx5IGV4cHJlc3NlZCBnZW5lcyIpICU+JQogIGthYmxlRXh0cmE6OmthYmxlX3N0eWxpbmcoInN0cmlwZWQiKQpgYGAKYGBge3IgYWxsX2Rpc3RfcGxvdH0KZ3Byb2ZpbGVyMjo6Z29zdHBsb3QodG9wX3Rlcm1zX2FsbCkgJT4lIHBsb3RseTo6bGF5b3V0KHRpdGxlID0gIk1hbmhhdHRhbiBwbG90IHNob3dpbmcgZGlzdHJpYnV0aW9uIG9mIHRlcm1zIGZyb20gZWFjaCBkYXRhIHNvdXJjZSIsIGZvbnQgPSBsaXN0KHNpemUgPSAxMCkpCmBgYAoKYGBge3IgY291bnRfdG9wX3Rlcm1zLCBlY2hvPUZBTFNFLCBtZXNzYWdlPUZBTFNFLCByZXN1bHRzPSdoaWRlJ30KbGVuZ3RoKHRvcF90ZXJtcyR0ZXJtX25hbWUpCmBgYAoKIyMgRGlzY3Vzc2lvbgoKMS4gV2UgdXNlZCBnOlByb2ZpbGVyIGFzIHdlIGhhdmUgZXh0ZW5zaXZlbHkgZGlzY3Vzc2VkIGFib3V0IGl0IGluIGNsYXNzLiBJdCBoYXMgYSBuaWNlIHdlYi1iYXNlZCBpbnRlcmZhY2UgYXMgd2VsbCBhcyBlYXN5LXRvLXVzZSBBUElzIGluIHRoZSBmb3JtIG9mIGFuIFIgcGFja2FnZS4gRnVydGhlcm1vcmUsIHRoZSBkYXRhIHNvdXJjZXMgb24gZzpQcm9maWxlciBpcyBmcmVxdWVudGx5IHVwZGF0ZWQgYW5kIGluY2x1ZGUgdGhlIGRhdGEgc291cmNlcyB0aGF0IHdlIGFyZSBtb3N0IGludGVyZXN0ZWQgaW4uCgoyLiBXZSB1c2VkIEdPIEJpb2xvZ2ljYWwgUHJvY2VzcywgR08gTW9sZWN1bGFyIEZ1bmN0aW9uLCBhbmQgS0VHTy4gV2UgY2hvc2UgdGhlc2UgZGF0YSBzb3VyY2VzIHNpbmNlIHRoZXkgYXJlIGFsc28gdXNlZCBieSB0aGUgYXV0aG9yIG9mIHRoZSBvcmlnaW5hbCBwYXBlciBmcm9tIHdoaWNoIEkgb2J0YWluZWQgdGhlIGRhdGFzZXQuIEhvd2V2ZXIsIHNpbmNlIEtFR08gaXMgYSBjb21tZXJjaWFsIGRhdGEgc291cmNlLCBpZiBpdCB3YXMgbm90IGZvciB0aGF0IGZhY3QgdGhhdCB0aGUgb3JpZ2luYWwgcGFwZXIgdXNlZCBpdCwgSSB3b3VsZCBwZXJzb25hbGx5IHJlZnJhaW4gZnJvbSB1c2luZyBpdC4gVGhlIG9yaWdpbmFsIGF1dGhvciBhbHNvIHVzZWQgb3RoZXIgZGF0YSBzb3VyY2VzIGluY2x1ZGluZyBDYW5vbmljYWwgUGF0aHdheXMgYnV0IHNpbmNlIGl0IGlzIG5vdCBwYXJ0IG9mIGc6UHJvZmlsZXIsIHdlIGRpZCBub3QgaW5jbHVkZSB0aGVzZSBkYXRhIHNvdXJjZXMuIFRoZSBhbm5vdGF0aW9uIHNvdXJjZSB2ZXJzaW9ucyBhcmUgYXMgZm9sbG93czogRW5zZW1ibCAxMDUsIEVuc2VtYmwgR2Vub21lcyA1MiAoZGF0YWJhc2UgYnVpbHQgb24gMjAyMi0wMi0xNCkKCjMuIEZvciBhbGwgdGhyZWUgYW5hbHlzaXMgKHVzaW5nIHVwcmVndWxhdGVkLCBkb3ducmVndWxhdGVkLCBhbGwgZGlmZmVyZW50aWFsbHkgZXhwcmVzc2VkKSwgd2UgdXNlZCBhIHRocmVzaG9sZCBiZXR3ZWVuIDIgYW5kIDUwMC4gV2Ugc2V0IHRoZSB1cHBlciBib3VuZCB0byA1MDAgYmVjYXVzZSB3ZSBkbyBub3Qgd2FudCB0byBpbmNsdWRlIG92ZXJseSBicm9hZCBhbmQgZ2VuZXJpYyB0ZXJtcyB0aGF0IHdpbGwgbm90IGdpdmUgdXMgbWVhbmluZ2Z1bCBpbnNpZ2h0cyBpbnRvIHRoZSByb2xlcyBvZiB0aGUgZGlmZmVyZW50aWFsbHkgZXhwcmVzc2VkIGdlbmVzLiBUaGUgc2V0IG9mIHVwcmVndWxhdGVkIGdlbmVzIHJldHVybmVkIDQzMyBnZW5lc2V0czsgdGhlIHNldCBvZiBkb3ducmVndWxhdGVkIGdlbmVzIHJldHVybmVkIDU2MCBnZW5lc2V0czsgdGhlIHNldCBvZiBhbGwgZGlmZmVyZW50aWFsbHkgZXhwcmVzc2VkIGdlbmVzIHJldHVybmVkIDYxNiBnZW5lIHNldHMuCgo0LiBUaGUgcmVzdWx0IHVzaW5nIHRoZSB3aG9sZSBsaXN0IChzZXQgb2YgYWxsIGRpZmZlcmVudGlhbGx5IGV4cHJlc3NlZCBnZW5lcykgaXMgbW9yZSBwcmVkb21pbmFudGx5IHJlcHJlc2VudGVkIGJ5IHRoZSBkb3ducmVndWxhdGVkIGdlbmVzLiBJdCBhbHNvIGRvZXMgbm90IHByb3ZpZGUgYSBsb3Qgb2YgaW5zaWdodHMgaW50byB0aGUgcm9sZXMgb2YgdGhlIGdlbmVzIGFzIGl0IGlzIGEgbWl4IG9mIGRyYXN0aWNhbGx5IGRpZmZlcmVudCBhbmQgc2VlbWluZ2x5IHVucmVsYXRlZCB0ZXJtcyAoZS5nLiBtaXRvdGljIG51Y2xlYXIgZGl2aXNpb24sIG9yZ2FuZWxsZSBmaXNzaW9uLCByZXNwb25zZSB0byBlbmRvcGxhc21pYyByZXRpY3VsdW0gc3RyZXNzLCBldGMuKS4gSG93ZXZlciwgYnkgdXNpbmcgc2VwYXJhdGluZyBpbnRvIHVwcmVndWFsdGVkIGFuZCBkb3ducmVndWxhdGVkIGdlbmVzIGFuZCBwZXJmb3JtaW5nIHRoZSBnZW5lIGVucmljaG1lbnQgYW5hbHlzaXMgc2VwYXJhdGVseSwgd2UgZ2V0IG1vcmUgbWVhbmluZ2Z1bCB0ZXJtczogdGhlIHVwcmVndWFsdGVkIGdlbmVzIGFyZSBtb3N0bHkgYXNzb2NpYXRlZCB3aXRoIHBhdGh3YXlzIGFuZCBwcm9jZXNzZXMgaW52b2x2aW5nIGVuZG9wbGFzbWljIHJldGljdWx1bSB3aGVyZWFzIHRoZSBkb3ducmVndWxhdGVkIGdlbmVzIGFyZSBtb3N0bHkgYXNzb2NpYXRlZCB3aXRoIHRoZSBjZWxsIGN5Y2xlLgoKCiMgSW50ZXJwcmV0YXRpb24KCjEuIFllcy4gVGhlIG92ZXJyZXByZXNlbnRhdGlvbiBhbmFseXNpcyByZXN1bHRzIHN1cHBvcnQgdGhlIGNvbmNsdXNpb24gZGlzY3Vzc2VkIGluIHRoZSBvcmlnaW5hbCBwYXBlci4gVGhlIG9yaWdpbmFsIHBhcGVyIGNsYWltcyB0aGF0IENCRCB0cmVhdG1lbnQgY2FuIGluaGliaXQgU0FSUy1Db1YtMiByZXBsaWNhdGlvbiB0aHJvdWdoIHRoZSBob3N0J3MgRVIgc3RyZXNzIHJlc3BvbnNlIHBhdGh3YXkuIEFsdGhvdWdoIHdlIHdlcmUgbm90IGFibGUgdG8gdmVyaWZ5IHdoZXRoZXIgb3Igbm90IHRoaXMgaGFzIGFueSBhZmZlY3Qgb24gU0FSUy1Db1YtMiByZXBsaWNhdGlvbiwgd2UgYXJlIGFibGUgdG8gY29uZmlybSBiYXNlZCBvbiB0aGUgdG9wIHRlcm1zIHJldHVybmVkIGJ5IHRoZSBvdmVycmVwcmVzZW50YXRpb24gYW5hbHlzaXMgdGhhdCB0aGUgZ2VuZXMgYXNzb2NpYXRlZCB3aXRoIEVSIHN0cmVzcyByZXNwb25zZSBhcmUgaW5kZWVkIHVwcmVndWxhdGVkIGluIHRoZSBzYW1wbGVzIHRyZWF0ZWQgd2l0aCBDQkQuCgoyLiBUaGUgY29uY2x1c2lvbiB0aGF0IENCRCBpcyBjb3JyZWxhdGVkIHRvIHJlZHVjZWQgcmlzayBvciBzZXZlcml0eSBvZiBTQVJTLUNvVi0yIGlzIHN1cHBvcnRlZCBieSB0ZXN0aW5nIGFkdWx0IHBhdGllbnRzIGFzIHByZXNlbnRlZCBieSB0aGUgb3JpZ2luYWwgcGFwZXIuIFRoZXJlIGFyZSBhbHNvIG90aGVyIHBhcGVycyB3aG8gZGlzY3Vzc2VkIHRoZSByb2xlIG9mIENCRCBpbiBTQVJTLUNvVi0yIGluZmVjdGlvbiAodmFuIEJyZWVtYW4gZXQgYWwuKS4gVGhlIHJlc3VsdCBmcm9tIG91ciBvdmVycmVwcmVzZW50YXRpb24gYW5hbHlzaXMgaXMgc3VwcG9ydGVkIGJ5IHRoZSBvcmlnaW5hbCBwYXBlciwgaW4gd2hpY2ggdGhlIGF1dGhvciBoYXMgYWxzbyBwZXJmb3JtZWQgZ2VuZSBlbnJpY2htZW50IGFuYWx5c2lzIHdpdGggc2ltaWxhciBvdXRjb21lcy4gSG93ZXZlciwgc2luY2UgdGhpcyBpcyBzdGlsbCBhbiBlYXJseSByZXNlYXJjaCBpbiB0aGlzIHRvcGljIGFuZCBTQVJTLUNvVi0yIGNvbnRpbnVlcyB0byBldm9sdmUsIHRoZXJlIGRvZXMgbm90IHNlZW0gdG8gYmUgb3RoZXIgdW5yZWxhdGVkIGdyb3VwcyB3aG8gY291bGQgcHJvdmlkZSBhZGRpdGlvbmFsIHN1cHBvcnRpbmcgZXZpZGVuY2UgdG8gb3VyIHJlc3VsdHMgZnJvbSB0aGUgb3ZlcnJlcHJlc2VudGF0aW9uIGFuYWx5c2lzIGJlc2lkZXMgdGhlIG9yaWdpbmFsIHBhcGVyLgoKIyBKb3VybmFsCgpMaW5rIHRvIG15IGpvdXJuYWwgZW50cnkgZm9yIHRoaXMgYXNzaWdubWVudDogaHR0cHM6Ly9naXRodWIuY29tL2JjYjQyMC0yMDIyL0tldmluX0dhby93aWtpL0Fzc2lnbm1lbnQtMgoKIyBSZWZlcmVuY2VzCgotIENoZW4gWSwgTHVuIEFUTCwgU215dGggR0sgKDIwMTYpLiBGcm9tIHJlYWRzIHRvIGdlbmVzIHRvIHBhdGh3YXlzOiBkaWZmZXJlbnRpYWwgZXhwcmVzc2lvbiBhbmFseXNpcyBvZiBSTkEtU2VxIGV4cGVyaW1lbnRzIHVzaW5nIFJzdWJyZWFkIGFuZCB0aGUKICBlZGdlUiBxdWFzaS1saWtlbGlob29kIHBpcGVsaW5lLiBGMTAwMFJlc2VhcmNoIDUsIDE0MzgKLSBEdXJpbmNrLCBTLiwgU3BlbGxtYW4sIFAuIFQuLCBCaXJuZXksIEUuLCAmIEh1YmVyLCBXLiAoMjAwOSkuIE1hcHBpbmcgaWRlbnRpZmllcnMgZm9yIHRoZSBpbnRlZ3JhdGlvbiBvZiBnZW5vbWljIGRhdGFzZXRzIHdpdGggdGhlIFIvQmlvY29uZHVjdG9yIHBhY2thZ2UgYmlvbWFSdC4gTmF0dXJlIC0gcHJvdG9jb2xzLCA0KDgpLCAxMTg04oCTMTE5MS4gaHR0cHM6Ly9kb2kub3JnLzEwLjEwMzgvbnByb3QuMjAwOS45NwotIE1hcnRpbiBNb3JnYW4gKDIwMjEpLiBCaW9jTWFuYWdlcjogQWNjZXNzIHRoZSBCaW9jb25kdWN0b3IgUHJvamVjdCBQYWNrYWdlIFJlcG9zaXRvcnkuIFIgcGFja2FnZSB2ZXJzaW9uIDEuMzAuMTYuCiAgaHR0cHM6Ly9DUkFOLlItcHJvamVjdC5vcmcvcGFja2FnZT1CaW9jTWFuYWdlcgotIE1jQ2FydGh5IERKLCBDaGVuIFkgYW5kIFNteXRoIEdLICgyMDEyKS4gRGlmZmVyZW50aWFsIGV4cHJlc3Npb24gYW5hbHlzaXMgb2YgbXVsdGlmYWN0b3IgUk5BLVNlcSBleHBlcmltZW50cyB3aXRoIHJlc3BlY3QgdG8gYmlvbG9naWNhbAogIHZhcmlhdGlvbi4gTnVjbGVpYyBBY2lkcyBSZXNlYXJjaCA0MCwgNDI4OC00Mjk3Ci0gTmd1eWVuLCBMLiBDLiwgWWFuZywgRC4sIE5pY29sYWVzY3UsIFYuLCBCZXN0LCBULiBKLiwgT2h0c3VraSwgVC4sIENoZW4sIFMuLU4uLCBGcmllc2VuLCBKLiBCLiwgRHJheW1hbiwgTi4sIE1vaGFtZWQsIEEuLCBEYW5uLCBDLiwgU2lsdmEsIEQuLCBHdWxhLCBILiwgSm9uZXMsIEsuIEEuLCBNaWxsaXMsIEouIE0uLCBEaWNraW5zb24sIEIuIEMuLCBUYXksIFMuLCBPYWtlcywgUy4gQS4sIFBhdWxpLCBHLiBGLiwgTWVsdHplciwgRC4gTy4sIOKApiBSb3NuZXIsIE0uIFIuICgyMDIxKS4gQ2FubmFiaWRpb2wgaW5oaWJpdHMgU0FSUy1DT1YtMiByZXBsaWNhdGlvbiBhbmQgcHJvbW90ZXMgdGhlIGhvc3QgaW5uYXRlIGltbXVuZSByZXNwb25zZS4gU2NpZW5jZSBBZHZhbmNlcy4gaHR0cHM6Ly93d3cuc2NpZW5jZS5vcmcvZG9pL2Ficy8xMC4xMTI2L3NjaWFkdi5hYmk2MTEwCi0gUm9iaW5zb24gTUQsIE1jQ2FydGh5IERKIGFuZCBTbXl0aCBHSyAoMjAxMCkuIGVkZ2VSOiBhIEJpb2NvbmR1Y3RvciBwYWNrYWdlIGZvciBkaWZmZXJlbnRpYWwgZXhwcmVzc2lvbiBhbmFseXNpcyBvZiBkaWdpdGFsIGdlbmUgZXhwcmVzc2lvbiBkYXRhLgogIEJpb2luZm9ybWF0aWNzIDI2LCAxMzktMTQwCi0gR3UsIFouICgyMDE2KSBDb21wbGV4IGhlYXRtYXBzIHJldmVhbCBwYXR0ZXJucyBhbmQgY29ycmVsYXRpb25zIGluIG11bHRpZGltZW5zaW9uYWwgZ2Vub21pYyBkYXRhLiBCaW9pbmZvcm1hdGljcy4KLSBLb2xiZXJnIEwsIFJhdWR2ZXJlIFUsIEt1em1pbiBJLCBWaWxvIEosIFBldGVyc29uIEggKDIwMjApLiDigJxncHJvZmlsZXIyLSBhbiBSIHBhY2thZ2UgZm9yIGdlbmUgbGlzdCBmdW5jdGlvbmFsIGVucmljaG1lbnQKYW5hbHlzaXMgYW5kIG5hbWVzcGFjZSBjb252ZXJzaW9uIHRvb2xzZXQgZzpQcm9maWxlci7igJ0gX0YxMDAwUmVzZWFyY2hfLCAqOSAoRUxJWElSKSooNzA5KS4gUiBwYWNrYWdlIHZlcnNpb24gMC4yLjEuCi0gU3RlZmFuIE1pbHRvbiBCYWNoZSBhbmQgSGFkbGV5IFdpY2toYW0gKDIwMjApLiBtYWdyaXR0cjogQSBGb3J3YXJkLVBpcGUgT3BlcmF0b3IgZm9yIFIuIGh0dHBzOi8vbWFncml0dHIudGlkeXZlcnNlLm9yZywKICBodHRwczovL2dpdGh1Yi5jb20vdGlkeXZlcnNlL21hZ3JpdHRyLgotIHZhbiBCcmVlbWVuLCBSLiBCLiwgTXVjaGlyaSwgUi4gTi4sIEJhdGVzLCBULiBBLiwgV2VpbnN0ZWluLCBKLiBCLiwgTGVpZXIsIEguIEMuLCBGYXJsZXksIFMuLCAmIFRhZmVzc2UsIEYuIEcuICgyMDIyKS4gQ2FubmFiaW5vaWRzIEJsb2NrIENlbGx1bGFyIEVudHJ5IG9mIFNBUlMtQ29WLTIgYW5kIHRoZSBFbWVyZ2luZyBWYXJpYW50cy4gSm91cm5hbCBvZiBuYXR1cmFsIHByb2R1Y3RzLCA4NSgxKSwgMTc24oCTMTg0LiBodHRwczovL2RvaS5vcmcvMTAuMTAyMS9hY3Muam5hdHByb2QuMWMwMDk0Ng==